﻿// Inner Fire 游戏引擎库
// CharaAnimation - 用于载入一个对象设定
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：框架层(5)
// 用于预置对象的设置。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-21

#include "chara_animation.h"
#include <enum_parser.h>
#include <game/config/config_manager.h>
#include <game/resource/assets.h>
#include <graphics/imath.h>

using namespace ikit;

namespace ifire::game {
void ComboAction::Setup() { ConfigManager::Setup(attack); }

ComboAction::ComboAction(const ikit::XmlNode& node, int _index)
    : index(_index), attack(node.Text()) {}

void ComboInfo::Setup() {
  for (auto& i : actions) {
    i.Setup();
  }
}

ComboInfo::ComboInfo(const ikit::XmlNode& node) : name(node("Name")) {
  actions.reserve(node.GetChildCount());
  node.Foreach("Action", [this](XmlNode& n, int idx) //
      { actions.emplace_back(n, idx); });
}

CharaAnimation::CharaAnimation(
    ConfigManager* manager, const ikit::XmlNode& node)
    : ConfigInfo(manager, node("Name"))
    , locomotion(node("Locomotion"))
    , on_damage(node("Damage"))
    , on_hit(node("Hit")) {

  node.ReadPtrs("Combo", combo_);
}

CharaAnimation::~CharaAnimation() {
  for (auto i : combo_) {
    delete i;
  }
}

void CharaAnimation::Setup() {
  Assets::Setup(locomotion);
  Assets::Setup(on_damage);
  Assets::Setup(on_hit);
  for (auto i : combo_) {
    i->Setup();
  }
}

ComboInfo* CharaAnimation::GetCombo(ikit::sstr name) {
  return ikit::get_item_by_name(combo_, name);
}

static void GetHitPhaseContent(lua_State* L, HitPhase& phase, int index) {
  lua_set_int(L, "index", index++);
  lua_set_float(L, "percent", phase.percent);
  lua_set_float(L, "start_time", phase.GetStart());
  lua_set_float(L, "end_time", phase.GetEnd());
}

static void GetComboActionContent(
    lua_State* L, ComboAction& action, int index) {
  lua_set_int(L, "index", index);
  lua_set_string(L, "name", action.attack.name.c_str());
  // 这里得到的Action的AttackInfo则是和项目平级
  auto attack = action.attack.get();
  // 动画项目
  lua_set_string(L, "clip", attack->animation.name.c_str());
  lua_set_float(L, "duration", attack->GetDuration());
  lua_set_float(L, "cancel_time", attack->GetCancelTime());
  // 攻击Phase
  lua_set_items_table<HitPhase>(
      L, "phases", attack->hit_phases, GetHitPhaseContent);
}

static void GetComboInfoContent(lua_State* L, ComboInfo*& combo, int index) {
  lua_set_int(L, "index", index);
  lua_set_string(L, "name", combo->name.c_str());
  lua_set_items_table<ComboAction>(
      L, "actions", combo->actions, GetComboActionContent);
}

int CharaAnimation::GetData(lua_State* L) {
  // 创建根表
  lua_newtable(L); // chara_animation

  // 添加locomotion - 现在推送的是AnimationBlend用户数据
  lua_set_string(L, "locomotion", locomotion->name.c_str());
  lua_set_string(L, "on_damage", on_damage->GetAnimation()->name.c_str());
  lua_set_string(L, "on_hit", on_hit->GetAnimation()->name.c_str());

  // 增加连击。
  lua_set_items_table<ComboInfo*>(L, "combo", Combos(), GetComboInfoContent);

  // 现在栈顶就是完整的chara_animation表
  return 1;
}

} // namespace ifire::game